#pragma once
#include "vector2.h"
#include "vector3.h"
#include "quaternion.h"
#include "aabb.h"

#include <stdexcept>

namespace krryn{
namespace data{
	class md5_node_exception : public std::runtime_error{
	public:
		md5_node_exception(const std::string &a_Error);
		virtual ~md5_node_exception() throw() {}
	};

	class md5_node{
	public:
		enum{
			invalid_joint = INT_MIN // -1 is root node
		};

		virtual ~md5_node() {}
		virtual void validate() = 0;
	};

	class md5_vertex : public md5_node{
	public:
		math::uv m_UV;

		int m_WeightStart;
		int m_WeightCount;

		md5_vertex();

		virtual void validate();
	};

	class md5_triangle : public md5_node{
	public:
		int m_Vertices[3];

		md5_triangle();

		virtual void validate();
	};

	class md5_weight : public md5_node{
	public:
		int m_Joint;
		float m_Bias;
		math::vector3f m_Position;

		md5_weight();

		virtual void validate();
	};

	class md5_mesh : public md5_node{
	public:
		std::string m_Shader;

		int m_NumVertices;
		int m_NumTriangles;
		int m_NumWeights;

		md5_vertex *m_Vertices;
		md5_triangle *m_Triangles;
		md5_weight *m_Weights;

		md5_mesh();

		virtual ~md5_mesh();
		virtual void validate();
	};

	class md5_joint : public md5_node{
	public:
		std::string m_Name;
		int m_Parent;
		math::vector3f m_Position;
		math::quaternionf m_Rotation;

		md5_joint();

		virtual void validate();
	};

	class md5_animation : public md5_node{
	public:
		int m_NumFrames;
		int m_NumJoints;
		int m_FrameRate;

		md5_joint **m_SkeletalFrames;
		math::aabb *m_BoundingBoxes;

		md5_animation();
		virtual ~md5_animation();

		virtual void validate();
	};

	class md5_model : md5_node{
	public:
		int m_NumMeshes;
		int m_NumJoints;

		md5_mesh *m_Meshes;
		md5_joint *m_BindingPose;

		md5_model();
		virtual ~md5_model();

		void validate();
	};
}
}